home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
4_0
/
VIVIDUS
/
VECT.SIT
/
vect
/
vect.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-26
|
9KB
|
510 lines
#include "vect.h"
#include <math.h>
/* ======================================================================
Vector abstraction library.
This is part of the vect Vividus Source Code Library. See the
extern vect.doc documentation file for usage. See individual
routines for routine documentation.
Copyright 1991 by Vividus Consulting.
This is not public domain source code. You may not copy and
paste from this source code. Read your Vividus Licensing
agreement for details and other restrictions.
====================================================================== */
/* ============================================================ */
/* Globals: -------------------- */
vector vzero = {0.0,0.0,0.0};
vector vone = {1.0,1.0,1.0};
static union { short i[6]; double x; } naninit = { 0x3EA1, 0x0331 };
// double number = naninit.x;
vector vnav = {0.0,0.0,0.0}; // "Not a vector".
// Later each component will be
// replaced by nan(NANINIT).
vector vxaxis = {1.0,0.0,0.0};
vector vyaxis = {0.0,1.0,0.0};
vector vzaxis = {0.0,0.0,1.0};
CoordSys vWorldCoordSys = { {1.0, 0.0, 0.0},
{0.0, 1.0, 0.0},
{0.0, 0.0, 1.0}
};
/* ============================================================ */
/* Vector primitives: */
void
vunit (
vector *v,
vector *vo)
/*
Find the unit vector of v and return it in vo.
*/
{
vscale (1.0/vmag(v), v, vo);
}
void
vcopy (
vector *v,
vector *vo)
/*
vo = v
*/
{
vo->x = v->x;
vo->y = v->y;
vo->z = v->z;
}
void
vscale (
velem scalar,
vector *v,
vector *vo)
/*
vo = scalar * v
*/
{
vo->x = v->x * scalar;
vo->y = v->y * scalar;
vo->z = v->z * scalar;
}
void
vsub(
vector *a,
vector *b,
vector *v)
/*
v = a - b
*/
{
v->x = a->x - b->x;
v->y = a->y - b->y;
v->z = a->z - b->z;
}
void
vvect (
vector *a,
vector *b,
vector *v)
/*
Find the vector going from point a to point b.
*/
{
v->x = b->x - a->x;
v->y = b->y - a->y;
v->z = b->z - a->z;
}
void
vadd (
vector *a,
vector *b,
vector *v)
/*
v = a + b
*/
{
v->x = a->x + b->x;
v->y = a->y + b->y;
v->z = a->z + b->z;
return;
/* The following notice may not be removed under any
circumstance. See your licensing agreement. */
asm {
dc.b "vect Copyright 1991 Vividus Consulting"
}
}
void
vsadd(
vector *b,
velem m,
vector *x,
vector *v)
/*
v = b + mx
*/
{
register velem vx = b->x + m * x->x,
vy = b->y + m * x->y,
vz = b->z + m * x->z;
v->x = vx;
v->y = vy;
v->z = vz;
}
void
vcross (
vector *a,
vector *b,
vector *v)
/*
v = a cross b
*/
{
register velem vx = (a->y * b->z) - (a->z * b->y),
vy = (a->z * b->x) - (a->x * b->z),
vz = (a->x * b->y) - (a->y * b->x);
v->x = vx;
v->y = vy;
v->z = vz;
}
velem vdot (
vector *a,
vector *b)
/*
Returns the dot product of a and b.
*/
{
return(a->x * b->x + a->y * b->y + a->z * b->z);
}
velem
vmag (
vector *v)
/*
Returns the magnitude of v.
*/
{
double retval;
retval = v->x * v->x;
retval += v->y * v->y;
retval += v->z * v->z;
retval = sqrt(retval);
return (retval);
}
velem
vdist(vector *a, vector *b)
/*
Returns the distance between the two "points."
*/
{
vector v;
vsub(b, a, &v);
return(vmag(&v));
}
velem
vangle (
vector *a,
vector *b)
/*
Gives the angle (radians) between the two vectors.
The direction of the vectors is important.
*/
{
return( acos( vdot(a, b) / (vmag(a) * vmag(b)) ) );
}
void
vmul (
vector *a,
vector *b,
vector *v)
/*
Multiply the components of vector b by the components of a (and store in v).
*/
{
register velem vx = a->x * b->x,
vy = a->y * b->y,
vz = a->z * b->z;
v->x = vx;
v->y = vy;
v->z = vz;
}
/* ============================================================ */
/* Useful vector routines: */
void
vsphere2v (
double rho,
double phi,
double theta,
vector *v)
/*
Given the spherical coordinates, the cartesian point is returned.
*/
{
v->x = rho * sin(phi) * cos(theta);
v->y = rho * sin(phi) * sin(theta);
v->z = rho * cos(phi);
}
void
vv2sphere (
vector *v,
double *rho,
double *phi,
double *theta)
/*
Given the cartesian point, the spherical coordinates are returned.
*/
{
*rho = vmag(v);
*theta = atan2(v->y, v->x);
*phi = vangle(v, &vzaxis);
}
void
vnorm(vector x[], vector *norm)
/*
Returns the unit "normal" of the plane identified by the first three points
of x. The "outside" of the plane is determined by the clockwise order of
the points.
*/
{
vector a, b;
vvect(&x[0], &x[1], &a);
vvect(&x[1], &x[2], &b);
vcross(&a, &b, norm);
vunit(norm, norm);
}
void
vmatmul (
vector *a,
vector m[], /* A 3x3 matrix. The first vector is the first row. */
vector *v)
/*
A vector and 3x3 matrix multiplication routine.
v = a * m
*/
{
vector *m1,
*m2,
*m3;
register velem vx, vy, vz;
m1 = &(m[0]);
m2 = &(m[1]);
m3 = &(m[2]);
vx = a->x * m1->x + a->y * m1->y + a->z * m1->z;
vy = a->x * m2->x + a->y * m2->y + a->z * m2->z;
vz = a->x * m3->x + a->y * m3->y + a->z * m3->z;
v->x = vx;
v->y = vy;
v->z = vz;
}
void
vcmin(
vector *a,
vector *b,
vector *out)
/*
This function returns the component minimums of a & b in out.
*/
{
if (a->x < b->x)
out->x = a->x;
else
out->x = b->x;
if (a->y < b->y)
out->y = a->y;
else
out->y = b->y;
if (a->z < b->z)
out->z = a->z;
else
out->z = b->z;
}
void
vcmax(
vector *a,
vector *b,
vector *out)
/*
This function returns the component maximums of a & b in out.
*/
{
if (a->x > b->x)
out->x = a->x;
else
out->x = b->x;
if (a->y > b->y)
out->y = a->y;
else
out->y = b->y;
if (a->z > b->z)
out->z = a->z;
else
out->z = b->z;
}
Boolean vvalid(vector *v)
/*
Returns true if every component of v is a "valid" floating point number.
Note: Presently, this just makes sure no component of v is a coponent
of vnav.
*/
{
if ( (v->x == vnav.x) || (v->y == vnav.y) || (v->z == vnav.z) )
return (false);
else
return (true);
}
/* ============================================================ */
/* Operations on point/vector lists: */
void
vCopy(int n, vector x[], vector xn[])
/*
Copies the point list x to xn.
*/
{
int i;
for (i = 0; i < n; i++) {
vcopy(&x[i], &xn[i]);
}
}
void
vTranslate(int n, vector x[], vector *b, vector xn[])
/*
Translate the point list x by the amount of vector b.
Results are in xn.
*/
{
int i;
for (i = 0; i < n; i++) {
vadd(&x[i], b, &xn[i]);
}
}
void
vScale(int n, vector x[], vector *s, vector xn[])
/*
Scale each component of the vectors in the vector list by the
specified amounts in the components of s.
Results are in xn.
*/
{
int i;
for (i = 0; i < n; i++) {
vmul(&x[i], s, &xn[i]);
}
}
void
vRotate3(
int n, vector x[],
vector *a, vector *b, vector *c,
vector xn[])
/*
Rotate the point list about the axis defined by the vector
(b - a) cross (c - b)
and the location
b.
The amount and direction of rotation is determined by the angle
and angle direction between the vectors:
(b - a), and (c - b).
Results are in xn.
*/
{
vector av, bv, norm, xa, ya;
double angle;
register double dy, dx;
vsub(a, b, &av);
vunit(&av, &xa);
vsub(c, b, &bv);
vcross(&av, &bv, &norm);
vcross(&xa, &norm, &ya);
vunit(&ya, &ya);
dy = vdot(&ya, &bv);
dx = vdot(&xa, &bv);
angle = atan2(dy, dx);
vRotate(n, x, b, &norm, angle, xn);
}
void
vRotate(int n, vector x[], vector *o, vector *norm, velem angle, vector xn[])
/*
Rotate the point list about the given axis by the given angle.
The point o and the direction norm determine the axis of rotation.
Results are in xn.
*/
{
/*
From:
C Park, "Interactive Microcomputer Graphics," Addison Wesley, 1985, p149.
*/
vector q, *qp = &q, *xi, *xo;
vector mat[3];
velem ct = cos(angle);
velem st = sin(angle);
int i;
#define A (mat[0].x)
#define B (mat[0].y)
#define C (mat[0].z)
#define D (mat[1].x)
#define E (mat[1].y)
#define F (mat[1].z)
#define G (mat[2].x)
#define H (mat[2].y)
#define I (mat[2].z)
#define a (qp->x)
#define b (qp->y)
#define c (qp->z)
vunit (norm, &q);
A = a * a + (1.0 - a * a) * ct;
B = a * b * (1.0 - ct) + c * st;
C = a * c * (1.0 - ct) - b * st;
D = a * b * (1.0 - ct) - c * st;
E = b * b + (1.0 - b * b) * ct;
F = b * c * (1.0 - ct) + a * st;
G = a * c * (1.0 - ct) + b * st;
H = b * c * (1.0 - ct) - a * st;
I = c * c + (1.0 - c * c) * ct;
for (i = 0; i < n; i++) {
xi = &x[i];
xo = &xn[i];
vsub(xi, o, xo);
vmatmul(xo, mat, xo);
vadd(xo, o, xo);
}
}